# Python Code to Create and Read a document

from pymongo import MongoClient 
from bson.objectid import ObjectId 

class AnimalShelter(object): 
    """ CRUD operations for Animal collection in MongoDB """ 

    def __init__(self, username, password): 
        # Initializing the MongoClient. This helps to access the MongoDB 
        # databases and collections. This is hard-wired to use the aac 
        # database, the animals collection, and the aac user. 
        # 
        # You must edit the password below for your environment. 
        # 
        # Connection Variables 
        # 
        USER = username  # this is username
        PASS = password  #this is user's password
        HOST = 'localhost'   #host name
        PORT = 27017        #port used
        DB = 'aac'          #Database name
        COL = 'animals'     #collection used
        # 
        # Initialize Connection 
        # 
        self.client = MongoClient('mongodb://%s:%s@%s:%d' % (USER,PASS,HOST,PORT))   #connects to mongoDB
        self.database = self.client['%s' % (DB)]   #connects to database
        self.collection = self.database['%s' % (COL)]  #connects to collection

    # Creates method to return the next available record number for use in the create method  
    def getNextRecNum(self, data):
        max_rec_num = self.database.animals.count_documents({}) #counts the number of total documents in the database
        nextRecNum = max_rec_num + 1  #adds 1 to increment the rec_num for the new entry
        return nextRecNum  #sends the new rec_num back to add to the new document
    # Creates method to implement the C in CRUD. 
    def create(self, data):    
        if data is not None: #checks if nothing is passed in
            next_rec_num = self.getNextRecNum(data)  #calls the getNextRecNum() method to get the new rec_num for the new document being added
            data['rec_num'] = next_rec_num  #adds the new rec_num to the new document
            creationResults = self.database.animals.insert_one(data).acknowledged  # data should be dictionary, new doc is added & confirmed true
            return creationResults
        else: 
            raise Exception("Nothing to save, because data parameter is empty") #raises an exception if nothing is passed in
            return False
    # Creates method to implement the R in CRUD.
    def read(self, query):
        if query is not None:  #checks if nothing is passed in
            cursor = self.database.animals.find(query)  #uses find() to search the collection
            readResults = [doc for doc in cursor]  #uses the cursor to store the results
            return readResults  #returns the search results
        else:
            raise Exception("Nothing to save, because data parameter is empty")  #raises an exception if nothing is passed in
            return []  #returns an empty list if a document is not found
    # Creates a method to implement the U in CRUD.
    def update(self, query, data):    # passes in query to search for the record to be updated and the new updated data
        if data is not None:   #checks if nothing is not passed in
            newData = {"$set": data}  # prepares a variable to set the new updated info
            updateResults = self.database.animals.update_one(query, newData)  #calls mongodb to update the record with new updated data
            return updateResults.modified_count  # returns the number of objects updated
        else:
            raise Exception("Nothing to update, because data parameter is empty")  #raises an exception if nothing is passed in
            return False
    # Creates a method to implement the D in CRUD.
    def delete(self, data):
        if data is not None:  #checks if nothing is passed in 
            deleteResults = self.database.animals.delete_one(data)  #deletes the document from the database
            return deleteResults.deleted_count  #returns the number of objects deleted
        else:
            raise Exception("Nothing to delete, because data parameter is empty")  #raises an exception if nothing is passed in
            return False